
#include "dlfacade.h" 
#include <string.h>
#include <sstream>
#include <sys/types.h>
#include <iostream>
#include <dlfcn.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include "Debug.h"

using namespace std;

DlFacade * DlFacade::_instance = 0;

DlFacade::DlFacade() 
{
	m_pStorage = NULL;
	dl_handle = NULL;
	cout<<">>>>>>>>>>>>  create object DlFacade!"<<endl;
}

DlFacade::~DlFacade()
{
	if(dl_handle != NULL)
	{
		if(m_pStorage != NULL)
		{
			void * (*destroy_storage)(IStorage *);
			destroy_storage = (void *(*)( IStorage *))dlsym(dl_handle, "destroy_storage");
			destroy_storage(m_pStorage);
		}
		dlclose(dl_handle);
	}
	cout<<">>>>>>>>>>>>  free object DlFacade now!"<<endl;
}

DlFacade * DlFacade::Instance(const char *so, const char *config)
{
	if (NULL == _instance) 
	{
		_instance = new DlFacade();
		if ( !_instance->Startup(so, config) ) {
			delete _instance; 
			_instance = NULL;
		}
	}
	return _instance;
}

void DlFacade::Release(bool bForce)
{
	if (_instance) 
	{
		if(bForce)
		{
			delete _instance; 
			_instance = NULL;
		}
	}
}

bool  DlFacade::Startup(const char *so, const char *config)
{
	if(so == NULL || strlen(so) < 1 )
		return false;

	struct stat st;
	if (lstat(so , &st) != 0)
	{	ERRO<< " file not exist:"<< so <<endl ;
		return false;
	}
	if (lstat(config , &st) != 0)
	{	ERRO<< " file not exist:"<< config <<endl ;
		return false;
	}

	dl_handle = dlopen(so, RTLD_LAZY);
	if (!dl_handle)
	{
		ERRO<< "dlopen error! " << endl;
		return false;
	}
	dlerror(); //clear any error
	IStorage * (*create_storage)(const char *);
	create_storage = (IStorage *(*)(const char *))dlsym(dl_handle, "create_storage");
	if (create_storage  == NULL)
	{
		ERRO<<"dlsym error "<<endl;
                perror("dlsym");
		dlclose(dl_handle);
		return false;
	}
	m_pStorage = create_storage(config );
	if (m_pStorage == NULL)
	{
		perror("create_storage");
		dlclose(dl_handle);
                return false;

	}
	return true;
}

IStorage *DlFacade::GetStorage()
{
    return m_pStorage;
} 

